
#ifndef GRAPH_HPP_
#define GRAPH_HPP_

#include <iostream>
#include <stdio.h>
#include <string>
#include "../list/list.hpp"
#include "edge.hpp"
#include "node.hpp"
#include "graphIterator.hpp"

#define OK 1
#define ERROR 0

/**
 * Class Graph: contiene al grafo sobre el cual se trabajara
 */
class Graph {
private:
	List<Node> 	nodes;
    int 	 	numberOfNodes;

public:

    /**
     * Constructor por defecto de la clase grafo.
     */
	Graph();

	/**
	 * Metodo getter de la cantidad de nodos del grafo.
	 * @return Retorna la cantidad de nodos del grafo.
	 */
    int getNumberOfNodes();

    /**
     * Retorna un puntero a la estructura de nodos.
     * @return Retorna un puntero a la estructura de nodos.
     */
    List<Node>* getNodes();

    /**
     * Busca y retorna el id de nodo pasado por parametro.
     * @param id de clase std::string.
     * @return Retorna un puntero al nodo si lo encontro.
     * @return NULL en caso de no haberlo encontrado.
     */
    Node* getNode(std::string id);

    /**
     * Busca el id de nodo pasado por parametro, para luego
     * buscar la arista de id = edgeId.
     * @param edgeId de clase std::string.
     * @param nodeId de clase std::string.
     * @return Retorna un puntero a la arista buscada si la encuentro.
     * @return NULL en caso de no haberla encontrado.
     */
    Edge* getEdge(std::string edgeId, std::string nodeId);

    /**
     * Agrega el nodo pasado por parametro al grafo.
     * @param node de Clase Node.
     */
	void addNode(Node *node);

	/**
	 * Agrega la arista pasado por parametro en la estructura
	 * de aristas del nodo que tiene como origen.
	 * @param edge de clase Edge.
	 * @return OK en caso de haber agregado la arista correctamente.
	 * @return ERROR en caso de no haber podida insertar la arista.
	 */
	int addEdge(Edge *edge);

	/**
	 * Busca el id de nodo pasado por parametro.
	 * @param node de clase Node.
	 * @param idNode de clase std::string.
	 * @return OK en caso de encontrar el nodo buscado.
	 * @return ERROR en caso de no haber encontrado el nodo.
	 */
	int modifyNode(Node node, std::string idNode);

	/**
	 * Busca el id de nodo que tiene como origen la lista,
	 * para luego buscar dentro de sus aristas la correspondiente.
	 * @param edge de clase Edge.
	 * @param idEdge de clase std::string.
	 * @return OK en caso de encontrar la arista buscada.
	 * @return ERROR en caso de no haber encontrado la arista.
	 */
	int modifyEdge(Edge edge, std::string idEgde);

	/**
	 * Busca el nodo por el id pasado por parametro,
	 * al encontrarlo lo borra para luego pasar borrar las
	 * aristas que tenian como destino ese nodo.
	 * @param id de clase std::string.
	 * @return OK en caso de haber hecho el proceso correctamente.
	 * @return ERROR en caso de haber encontrado algun error.
	 */
	int deleteNode(std::string id);

	/**
	 * Busca en el nodo con id = nodeId la arista de id = edgeId,
	 * si la encuentra la elimina.
	 * @param nodeId de clase std::string.
	 * @param edgeId de clase std::string.
	 * @return OK en caso de haber encontrar y removido la arista.
	 * @return ERROR en caso de no haberla encontrado.
	 */
	int deleteEdge(std::string nodeId, std::string edgeId);

	/**
	 * TODO
	 */
	//GraphIterator iterator();

	void cleanBestPathValues();

	/**
	 * Destructor de la clase Graph.
	 */
    virtual ~Graph();   
};

#endif /* GRAPH_HPP_ */
